package robots;

import java.awt.Color;
import java.util.Vector;
import java.awt.geom.Point2D;

import robocode.AdvancedRobot;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.ScannedRobotEvent;

public class MataTudo extends AdvancedRobot{

	ScannedRobotEvent lastEvent;
	private boolean sentidoFrente; 

	private double posXEnemy;
	private double posYEnemy;
	private double giroEnemy;
	private double distanciaEnemy;
	private long timeEnemy;
	private int direcao = 1;
	private double headingEnemy;
	private double enemySpeed;
	private long turnRate;
	

	public void run(){

		setColors(new Color(90, 55, 55), Color.black, Color.red);
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
		turnRadarRightRadians(2 * Math.PI);
		
		while(true){

			doMoviment();
			doScanner();
			doGun();
			//doMoviment();
			//fire(3);
			execute();

		}
	}

	@Override
	public void onScannedRobot(ScannedRobotEvent event) {
		// TODO Auto-generated method stub
		if(lastEvent == null){
			lastEvent = event;
		}
		turnRate = getTurnRate(getHeadingRadians(), lastEvent.getHeadingRadians(), getTime(), lastEvent.getTime());
		
		double giroRobo = (getHeadingRadians() + event.getBearingRadians()) % (2 * Math.PI);

		posXEnemy = getX() + Math.sin(giroRobo) * event.getDistance();
		posYEnemy = getY() + Math.cos(giroRobo) * event.getDistance();
		giroEnemy = event.getBearingRadians();
		headingEnemy = event.getHeadingRadians();
		enemySpeed = event.getVelocity();
		timeEnemy = getTime();
		
		lastEvent = event;
		/*if(getEnergy() < 50){
			baterRetirada();
		}
		avancar();*/
	}

	/*public void baterRetirada(){
		fire(2);
		back(200);
	}

	public void avancar(){
		ahead(100);
	}
*/
	/*
	public void onHitWall(HitWallEvent event) {
		// TODO Auto-generated method stub
		mudarSentido();
	}

	public void mudarSentido(){
		if (getTime() % 10 == 0)  { 		
			direcao *= -1;		
			setAhead(direcao * 300);				
		}
		//
		setTurnLeftRadians(giroEnemy + (Math.PI / 2));
	}
	*/
	
	public void doMoviment(){
		if (getTime() % 20 == 0)  { 		
			direcao *= -1;		
			setAhead(direcao * 300);				
		}
		//
		setTurnRightRadians(giroEnemy + (Math.PI / 2));
	}

	public double advinharXEnemy(){
		return posXEnemy + (enemySpeed * Math.sin(headingEnemy + turnRate));
	}

	public double advinharYEnemy(){
		return posYEnemy + (enemySpeed * Math.cos(headingEnemy + turnRate));
	}
	
	public long getTurnRate(double enemyHeading, double lastEnemyHeading,long timeNow, long timeBefore){
		return (long) ((enemyHeading - lastEnemyHeading) / (timeNow - timeBefore));
	}
	
	public void doScanner() {
		double deslocamentoRadar;
		//se por um intervalo de tempo não encontrar o inimigo
		//gira o radar
		if (getTime() - timeEnemy > 4) { 	
			deslocamentoRadar = 360;		
		} else {	

		//seta a quantidade necessária para rotação do radar de acordo com a posicao do inimigo
		deslocamentoRadar = getRadarHeadingRadians() - absbearing(getX(),getY(),posXEnemy,posYEnemy);

		if (deslocamentoRadar < 0)
			deslocamentoRadar -= Math.PI/8;
		else
			deslocamentoRadar += Math.PI/8; 
		}
		
		//gira o radar
		setTurnRadarLeftRadians(NormaliseBearing(deslocamentoRadar));
	}
	
	public void doGun() {

		//predição do inimigo e rotação da mira para ele
		double rotacaoArma = getGunHeadingRadians() - absbearing(getX(),getY(),advinharXEnemy(),advinharYEnemy());
		setTurnGunLeftRadians(NormaliseBearing(rotacaoArma));
	}

	
	public double absbearing( double x1,double y1, double x2,double y2 )
	{
		double xo = x2-x1;
		double yo = y2-y1;
		double h = getDistanciaEuclidiana( x1,y1, x2,y2 );
		if( xo > 0 && yo > 0 )
		{
			return Math.asin( xo / h );
		}
		if( xo > 0 && yo < 0 )
		{
			return Math.PI - Math.asin( xo / h );
		}
		if( xo < 0 && yo < 0 )
		{
			return Math.PI + Math.asin( -xo / h );
		}
		if( xo < 0 && yo > 0 )
		{
			return 2.0*Math.PI - Math.asin( -xo / h );
		}
		return 0;
	}
	
	public double getDistanciaEuclidiana( double x1,double y1, double x2,double y2 )
	{
		double xo = x2-x1;
		double yo = y2-y1;
		double h = Math.sqrt( xo*xo + yo*yo );
		return h;	
	}

	//normaliza o giro
	public double NormaliseBearing(double ang) {
		if (ang > Math.PI)
			ang -= 2 * Math.PI;
		if (ang < - Math.PI)
			ang += 2 * Math.PI;
		return ang;
	}

}
